﻿#include "MaterialVectorOperationNodeView.h"

#include "MaterialGraph/Pin/MaterialGraphPinView.h"

#include "Widgets/TextWidget.h"
#include "Widgets/RectangleWidget.h"
#include "Widgets/ImageWidget.h"
#include "Widgets/EditorCheckBoxWidget.h"
#include "Widgets/Mouse/MouseWidget.h"
#include "Widgets/Keyboard/KeyboardWidget.h"

#include "Framework/Editor.h"
#include "Theme/EditorTheme.h"

#include "Asset/EditorDefaultPackage.h"
#include "VectorOperation.h"

void RMaterialVectorOperationNodeView::BindViewModel(TSharedObjectPtr<RMaterialGraphNodeViewModel> InModel)
{
    Super::BindViewModel(InModel);
    OperationViewModel = InModel;
}

void RMaterialVectorOperationNodeView::RegenerateContentWidget()
{
    Super::RegenerateContentWidget();

    //添加一个输出引脚
    if(OperationViewModel->IsOutputFloat())
    {
        auto OutputLine=CreateSimpleOutputPinWidget(RootWidget,RootWidget,1,1);
    }
    else
    {
        auto OutputLine=CreateSimpleOutputPinWidget(RootWidget,RootWidget,0,1);
    }

    //使用一个组合框选择操作
    auto OperationLine=CreateLine(RootWidget,RootWidget,2);
    
    auto OperationLineBackground= NewWidget<RRectangleWidget>(OperationLine);
    OperationLineBackground->Anchor.VerticalFill(OperationLine);
    OperationLineBackground->Anchor.LeftReference=OperationLine;
    OperationLineBackground->Anchor.LeftOffset=OperationViewModel->LineHorizontalPadding;
    OperationLineBackground->Anchor.RightReference=OperationLine;
    OperationLineBackground->Anchor.RightOffset=OperationViewModel->LineHorizontalPadding;
    OperationLineBackground->FillColor= REditor::Get()->CurrentTheme->MaterialEditableBackground;
    OperationLineBackground->Radius=OperationViewModel->BackgroundRadius;

    auto OperationText=NewWidget<RTextWidget>(OperationLine);
    OperationText->Anchor.VerticalFill(OperationLine);
    OperationText->Anchor.LeftReference=OperationLineBackground;
    OperationText->Anchor.LeftOffset=OperationViewModel->LineHorizontalPadding;
    OperationText->Text=[this](){
        return OperationViewModel->GetOperationName();
    };
    OperationText->VerticalAlignment=ETextVerticalAlignment::Center;

    //this keyboard is just used to make popup menu auto hide
    auto PopupKeyboard=NewWidget<RKeyboardWidget>(OperationLine);
    RKeyboardWidgetWeakPtr WeakPopupKeyboard=PopupKeyboard;

    auto OperationMouse=NewWidget<RMouseWidget>(OperationLine);
    OperationMouse->Anchor.Fill(OperationLine);
    OperationMouse->AutoFocusTarget=PopupKeyboard;

    auto ComboBoxIcon=NewWidget<RImageWidget>(OperationLine);
    ComboBoxIcon->Anchor.RightReference=OperationLineBackground;
    ComboBoxIcon->Anchor.VerticalCenterReference=OperationLine;
    ComboBoxIcon->Width=20;
    ComboBoxIcon->Height=20;
    ComboBoxIcon->Image=
        REditorDefaultPackage::Get()->GetIcon(U"CodiconChevronDown");

    static const int64_t ColumnNum=4;
    static const int64_t LineNum=10;
    static const float LineWidth=100.0f;
    static const float LineHeight=20.0f;
    static const float PopupMenuHorizontalSpacing=10.0f;
    static const float PopupMenuVerticalSpacing=5.0f;
    static const float PopupMenuPadding=5.0f; //整个弹出菜单的上下左右边距

    auto ComboBoxPopup=NewWidget<RWidget>(RootWidget);
    PopupKeyboard->Anchor.Fill(ComboBoxPopup);
    ComboBoxPopup->Height= LineHeight*LineNum+PopupMenuVerticalSpacing*(LineNum-1)+PopupMenuPadding*2;
    ComboBoxPopup->Width= ColumnNum*LineWidth+ PopupMenuHorizontalSpacing*(ColumnNum-1)+PopupMenuPadding*2;
    ComboBoxPopup->Anchor.BottomReference=OperationText;
    ComboBoxPopup->Anchor.BottomReferenceEdge=EVerticalWidgetEdge::Top;
    ComboBoxPopup->Anchor.LeftReference=OperationText;
    ComboBoxPopup->Visible=[WeakPopupKeyboard](){
        return WeakPopupKeyboard->IsFocused();
    };

    auto PopupBackground=NewWidget<RRectangleWidget>(ComboBoxPopup);
    PopupBackground->Anchor.Fill(ComboBoxPopup);
    PopupBackground->FillColor= REditor::Get()->CurrentTheme->BackgroundColor;
    PopupBackground->Radius=4;
    RWidgetWeakPtr WeakPopupBackground=PopupBackground;

    //手动填充弹出菜单

    //在指定列指定行添加一标题，标题不能交互，只是用来显示

    auto AddTitle=[WeakPopupBackground](const CString& Title,int64_t LineIndex,int64_t ColumnIndex)
    {
        auto TitleText=NewWidget<RTextWidget>(WeakPopupBackground);
        TitleText->X= ColumnIndex*(LineWidth+PopupMenuHorizontalSpacing)+PopupMenuPadding;
        TitleText->Y= LineIndex*(LineHeight+PopupMenuVerticalSpacing)+PopupMenuPadding;
        TitleText->Width= LineWidth;
        TitleText->Height= LineHeight;
        TitleText->Text=Title;
        TitleText->Color= REditor::Get()->CurrentTheme->UninteractableTextColor;

    };

    auto AddOption=[WeakPopupBackground,WeakPopupKeyboard,this](EMaterialVectorOperationType Operation,int64_t LineIndex,int64_t ColumnIndex)
    {
        auto OptionBackground=NewWidget<RRectangleWidget>(WeakPopupBackground);
        OptionBackground->X= ColumnIndex*(LineWidth+PopupMenuHorizontalSpacing)+PopupMenuPadding;
        OptionBackground->Y= LineIndex*(LineHeight+PopupMenuVerticalSpacing)+PopupMenuPadding;
        OptionBackground->Width= LineWidth;
        OptionBackground->Height= LineHeight;
        OptionBackground->FillColor= REditor::Get()->CurrentTheme->HighlightColor;
        OptionBackground->Radius=4;

        auto OptionMouse=NewWidget<RMouseWidget>(WeakPopupBackground);
        OptionMouse->Anchor.Fill(OptionBackground);
        RMouseWidgetWeakPtr WeakOptionMouse=OptionMouse;
        OptionBackground->Fill=[WeakOptionMouse](){
            return WeakOptionMouse->IsHovered();
        };


        auto OptionText=NewWidget<RTextWidget>(WeakPopupBackground);
        OptionText->Anchor.Fill(OptionBackground);
        OptionText->VerticalAlignment=ETextVerticalAlignment::Center;
        OptionText->Text= WHE::ToString(Operation);

        OptionMouse->OnClicked.BindLambda([this,Operation,WeakPopupKeyboard](const SMouseButtonEvent&){
            OperationViewModel->SetOperationType(Operation);
            WeakPopupKeyboard->Unfocus();
            return true;
        });
    };

    AddTitle(U"四则运算",0,0);
    AddOption(EMaterialVectorOperationType::Add,1,0);
    AddOption(EMaterialVectorOperationType::Subtract,2,0);
    AddOption(EMaterialVectorOperationType::Multiply,3,0);
    AddOption(EMaterialVectorOperationType::Divide,4,0);
    AddOption(EMaterialVectorOperationType::AddAfterMultiply,5,0);
    AddOption(EMaterialVectorOperationType::Mod,6,0);


    AddTitle(U"复杂运算",0,1);
    AddOption(EMaterialVectorOperationType::CrossProduct,1,1);
    AddOption(EMaterialVectorOperationType::DotProduct,2,1);
    AddOption(EMaterialVectorOperationType::Project,3,1);
    AddOption(EMaterialVectorOperationType::Reflect,4,1);
    AddOption(EMaterialVectorOperationType::Refract,5,1);
    AddOption(EMaterialVectorOperationType::FaceForward,6,1);

    AddTitle(U"圆整",0,2);
    AddOption(EMaterialVectorOperationType::Absolute,1,2);
    AddOption(EMaterialVectorOperationType::Floor,2,2);
    AddOption(EMaterialVectorOperationType::Ceil,3,2);
    AddOption(EMaterialVectorOperationType::Fraction,4,2);
    AddOption(EMaterialVectorOperationType::Round,5,2);
    AddOption(EMaterialVectorOperationType::Loop,6,2);
    AddOption(EMaterialVectorOperationType::Snap,7,2);

    AddTitle(U"长度/距离",0,3);
    AddOption(EMaterialVectorOperationType::Length,1,3);
    AddOption(EMaterialVectorOperationType::Normalize,2,3);
    AddOption(EMaterialVectorOperationType::Scale,3,3);
    AddOption(EMaterialVectorOperationType::Distance,4,3);

    AddTitle(U"三角函数",5,3);
    AddOption(EMaterialVectorOperationType::Sin,6,3);
    AddOption(EMaterialVectorOperationType::Cos,7,3);
    AddOption(EMaterialVectorOperationType::Tan,8,3);

    //输入引脚
    int64_t CurrentLineIndex=3;
    switch(OperationViewModel->GetOperationType())
    {
        case EMaterialVectorOperationType::Absolute:
        case EMaterialVectorOperationType::Floor:
        case EMaterialVectorOperationType::Ceil:
        case EMaterialVectorOperationType::Fraction:
        case EMaterialVectorOperationType::Round:
        case EMaterialVectorOperationType::Normalize:
        case EMaterialVectorOperationType::Sin:
        case EMaterialVectorOperationType::Cos:
        case EMaterialVectorOperationType::Tan:
        case EMaterialVectorOperationType::Length:
        {
            //需要一个向量输入
            auto Input3DVector=CreateVector3DInputPinWidget(RootWidget,RootWidget,0,CurrentLineIndex);
            return;
        }

        case EMaterialVectorOperationType::Add:
        case EMaterialVectorOperationType::Subtract:
        case EMaterialVectorOperationType::Multiply:
        case EMaterialVectorOperationType::Divide:
        case EMaterialVectorOperationType::CrossProduct:
        case EMaterialVectorOperationType::Project:
        case EMaterialVectorOperationType::Reflect:
        case EMaterialVectorOperationType::Minimum:
        case EMaterialVectorOperationType::Maximum:
        case EMaterialVectorOperationType::Mod:
        case EMaterialVectorOperationType::Snap:
        case EMaterialVectorOperationType::DotProduct:
        case EMaterialVectorOperationType::Distance:
        {
            //需要两个向量输入
            auto Input3DVector1=CreateVector3DInputPinWidget(RootWidget,RootWidget,0,CurrentLineIndex);
            CurrentLineIndex+= InputPinViews[0]-> HasValidLink()? 1:4;
            auto Input3DVector2=CreateVector3DInputPinWidget(RootWidget,RootWidget,1,CurrentLineIndex);
            return;
        }

        case EMaterialVectorOperationType::AddAfterMultiply:
        case EMaterialVectorOperationType::FaceForward:
        case EMaterialVectorOperationType::Loop:
        {
            //需要三个向量输入
            auto Input3DVector1=CreateVector3DInputPinWidget(RootWidget,RootWidget,0,CurrentLineIndex);
            CurrentLineIndex+= InputPinViews[0]-> HasValidLink()? 1:4;
            auto Input3DVector2=CreateVector3DInputPinWidget(RootWidget,RootWidget,1,CurrentLineIndex);
            CurrentLineIndex+= InputPinViews[1]-> HasValidLink()? 1:4;
            auto Input3DVector3=CreateVector3DInputPinWidget(RootWidget,RootWidget,2,CurrentLineIndex);
            return;
        }




        case EMaterialVectorOperationType::Scale:
        {
            //需要一个向量输入和一个浮点输入
            auto Input3DVector=CreateVector3DInputPinWidget(RootWidget,RootWidget,0,CurrentLineIndex);
            CurrentLineIndex+= InputPinViews[0]-> HasValidLink()? 1:4;
            auto InputFloat=CreateVector1DInputPinWidgetWithoutLimit(RootWidget,RootWidget,3,CurrentLineIndex);
            return;
        }

        case EMaterialVectorOperationType::Refract:
        {
            //需要两个向量输入和一个浮点输入
            auto Input3DVector1=CreateVector3DInputPinWidget(RootWidget,RootWidget,0,CurrentLineIndex);
            CurrentLineIndex+= InputPinViews[0]-> HasValidLink()? 1:4;
            auto Input3DVector2=CreateVector3DInputPinWidget(RootWidget,RootWidget,1,CurrentLineIndex);
            CurrentLineIndex+= InputPinViews[1]-> HasValidLink()? 1:4;
            auto InputFloat=CreateVector1DInputPinWidgetWithoutLimit(RootWidget,RootWidget,3,CurrentLineIndex);
            return;
        }

        default:
        {
            assert(false);
        }
    
    }

}
